#ifndef JTYPE_H
#define JTYPE_H

#include <QTECore/jfunctiontraits.h>
#include <QtCore/qmetatype.h>
#include <typeinfo>

#ifdef __GNUC__
# include <cxxabi.h>
#endif

class QObject;

namespace QTE
{

#ifndef J_SCT
# define J_SCT(T, V)  static_cast<T>(V)
#endif //J_SCT

#ifndef J_RCT
# define J_RCT(T, V)  reinterpret_cast<T>(V)
#endif //J_RCT

#ifndef J_DCT
# define J_DCT(T, V)  dynamic_cast<T>(V)
#endif //J_DCT

#ifndef J_CCT
# define J_CCT(T, V)  const_cast<T>(V)
#endif //J_CCT

#ifndef J_OCT
# define J_OCT(T, V)  qobject_cast<T>(V)
#endif //J_OCT

/*------------------------------------------------------------------------------------------------*/

#if defined(_WIN64) || defined(__x86_64__) || defined(__amd64__) || defined(__arm64__) || defined(__aarch64__)
# define J_OS_64BIT
# define J_MAX_ABW  0xFFFFFFFFFFFFFFFFULL
typedef uint64_t  ABW_t;
#else
# define J_OS_32BIT
# define J_MAX_ABW  0xFFFFFFFFUL
typedef uint32_t  ABW_t;
#endif

template <typename T>
union AddrTlr
{
	T ptr;
	ABW_t addr;

	inline explicit AddrTlr(T ptr) : ptr(ptr) {}
	inline explicit AddrTlr(ABW_t addr) : addr(addr) {}
};

/*------------------------------------------------------------------------------------------------*/

template <class Class>
struct isBaseOfQObject : public std::is_base_of<QObject, Class> {};

struct ToAnyType
{
	template <typename T>
	operator T() {}
};

/*------------------------------------------------------------------------------------------------*/

#ifdef __GNUC__
# define ABI_CXA_DEMANGLE(name)  abi::__cxa_demangle(name, 0,0,0)
#else //Microsoft compilers need no special handling
# define ABI_CXA_DEMANGLE(name)  name
#endif //compiler

template <typename T>
inline const char *typeName(T &&t)
{
	return ABI_CXA_DEMANGLE(typeid(t).name());
}

template <typename T>
inline const char *typeName()
{
	return ABI_CXA_DEMANGLE(typeid(T).name());
}

/*------------------------------------------------------------------------------------------------*/

// Type registration for Reflection
#define QTE_type_register(Type, name, ...) \
	static int __attribute_used__ \
	__QTE_qRegisterMetaType_return##__VA_ARGS__ = \
	qRegisterMetaType<Type*>(name)

#define J_ARG(v)  QArgument<decltype(v)>(QTE::typeName(v), v)

/*------------------------------------------------------------------------------------------------*/

#ifdef __GNUC__
# ifndef __attribute_used__
#  define __attribute_used__  __attribute__((__used__))
# endif
# ifndef __attribute_unused__
#  define __attribute_unused__  __attribute__((__unused__))
# endif
#else //Microsoft compilers need no special handling
# ifndef __attribute_used__
#  define __attribute_use__
# endif
# ifndef __attribute_unused__
#  define __attribute_unused__
# endif
#endif

} //namespace QTE

Q_DECLARE_METATYPE(QTE::ABW_t)


#endif //JTYPE_H
